package com.cloudwise.config;

import cn.hutool.core.util.ObjectUtil;
import com.cloudwise.util.GetBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheKey;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * @author:高杰领
 * @date:2022/1/11 14:42
 * @description:
 * @version:
 **/
@Slf4j
public class MybatisCacheImpl implements Cache {
    RedisTemplate<String,Object> redisTemplate;
    private String id;
    /**
     *
     * @param id
     * @return
     * @author 高冷
     * @description:构造器
     * @date 2022/1/11 14:48
     */
    public MybatisCacheImpl(String id) {
        if(id==null){
            throw new RuntimeException("缓存必须有id");
        }
        this.id = id;
    }

    /**
     * @return The identifier of this cache
     * 返回此缓存的标识符
     */
    @Override
    public String getId() {
        return this.id;
    }

    /**
     * @param key   Can be any object but usually it is a {@link CacheKey}
     * @param value
     *
     */
    @Override
    public void putObject(Object key, Object value) {
        log.debug("设置缓存");
        if(ObjectUtil.isNull(redisTemplate)){
            redisTemplate = (RedisTemplate<String,Object>)GetBean.getBean("redisTemplate");
        }
        redisTemplate.opsForValue().set(key.toString(),value);

    }

    /**
     * @param key The key
     * @return The object stored in the cache.
     */
    @Override
    public Object getObject(Object key) {
        log.debug("获取缓存:"+this.id);
        if(ObjectUtil.isNull(redisTemplate)){
            redisTemplate = (RedisTemplate<String,Object>)GetBean.getBean("redisTemplate");
        }
        return redisTemplate.opsForValue().get(key.toString());
    }

    /**
     * As of 3.3.0 this method is only called during a rollback
     * for any previous value that was missing in the cache.
     * This lets any blocking cache to release the lock that
     * may have previously put on the key.
     * A blocking cache puts a lock when a value is null
     * and releases it when the value is back again.
     * This way other threads will wait for the value to be
     * available instead of hitting the database.
     *
     * @param key The key
     * @return Not used
     */
    @Override
    public Object removeObject(Object key) {
        if(ObjectUtil.isNull(redisTemplate)){
            redisTemplate = (RedisTemplate<String,Object>)GetBean.getBean("redisTemplate");
        }
        return redisTemplate.delete(key.toString());
    }

    /**
     * Clears this cache instance.
     */
    @Override
    public void clear() {
        log.debug("清空缓存");
        if(ObjectUtil.isNull(redisTemplate)){
            redisTemplate = (RedisTemplate<String,Object>)GetBean.getBean("redisTemplate");
        }
        redisTemplate.delete(redisTemplate.keys("*"+this.id+"*"));
    }

    /**
     * Optional. This method is not called by the core.
     *
     * @return The number of elements stored in the cache (not its capacity).
     */
    @Override
    public int getSize() {
        log.debug("获取所有的key数量");
        Integer execute = redisTemplate.execute(new RedisCallback<Integer>() {
            @Override
            public Integer doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.dbSize().intValue();
            }
        });
        return execute;
    }
}
